var net = require('net')
var { Config } = require('./config')
const actions = require('./actions')

var intevel = null;
var mainClient = null;
var tryFlag = true;
var slaveName = process.env.SLAVE_NAME ? process.env.SLAVE_NAME : Config.slaveName
var serverHost = process.env.SERVER_HOST ? process.env.SERVER_HOST : Config.serverHost


function getClient() {
    var sClient = net.connect({ port: Config.serverPort, host: serverHost }, function () {
        console.log("sClient: connected")
        console.log('   local = %s:%s', sClient.localAddress, sClient.localPort)
        console.log('   remote= %s:%s', sClient.remoteAddress, sClient.remotePort);

        sClient.setDefaultEncoding('utf-8')
        sClient.setEncoding('utf-8')
        sClient.setTimeout(5000)
        sClient.on('data', function (data) {
            var str = data.toString()
            var strss = str.split("\r\n")

            console.log(">> strss =%s", JSON.stringify(strss))
            
            strss.filter((it) => { return !(it == '') }).forEach(function (item) {

                console.log("sClient: from server:%s", item)
                var cmd = JSON.parse(item)
                switch (cmd.Action) {
                    case "REQLINK":
                        var id = cmd.id
                        var port = cmd.port
                        link(id, port)
                        break;

                    case "RESPCONFIRM":
                        var id = cmd.id
                        var port = cmd.port
                        setOn(id, port)
                    default:
                        break;
                }


            })


        })

        var regAction = new actions.REG(slaveName)
        console.log("sClient send regist :%s", JSON.stringify(regAction))

        sClient.write(JSON.stringify(regAction) + "\r\n");
        var hbeat = new actions.HBEAT(slaveName)
        intevel = setInterval(() => {
            sClient.write(JSON.stringify(hbeat) + "\r\n");
        }, 15000);
        mainClient = sClient;
    })

    sClient.on("error", function (err) {
        console.log("sClient onError:%s", err.message);
        sClient.destroy()
        clearInterval(intevel)
        intevel = null
        if (tryFlag) {
            tryFlag = false
            setTimeout(function () {
                tryFlag = true
                console.log('try to reconnect server')
                getClient()
            }, 5000)
        }
    })

    // sClient.on("close", function () {
    //     console.log("sClient closed");
    //     sClient.destroy()
    //     clearInterval(intevel)
    //     intevel=null
    //     if (tryFlag) {
    //         tryFlag = false
    //         setTimeout(function () {
    //             tryFlag = true
    //             console.log('try to reconnect server')
    //             getClient()
    //         }, 5000)
    //     }
    // })


}




var localSocketMap = new Map()
var dataSocketMap = new Map()

function link(id, port) {
    var localSocket = net.connect(port, 'localhost', function () {
        console.log('connected localhost  :%s', id)
    })

    localSocket.once("error", function (error) {
        console.log("localSocket onceError %s", error.message)
        if (dataSocketMap.has(id)) {
            dataSocketMap.get(id).end()
            dataSocketMap.get(id).destroy()
            dataSocketMap.delete(id)
        }
    })


    var dataSocket = net.connect(Config.serverDataPort, serverHost, function () {
        console.log("connected dataServer %s:%s  with %s", serverHost, Config.serverDataPort, id)
    })

    // dataSocket.setEncoding('utf-8')
    var respLink = new actions.RESPLINK(id, slaveName, port)

    console.log('dataSocket write first data:%s', JSON.stringify(respLink))
    dataSocket.write(JSON.stringify(respLink) + "\r\n");

    localSocketMap.set(id, localSocket)
    dataSocketMap.set(id, dataSocket)

}


function setOn(id, port) {

    let localSocket = localSocketMap.get(id)
    let dataSocket = dataSocketMap.get(id)

    localSocket.on('data', function (data) {
        console.log('<< local: %s -- %s', id, data.length)
        dataSocket.write(data)
    })

    localSocket.on('close', function () {
        console.log('localSocket onClose %s', id)
        localSocketMap.delete(id)

        if (dataSocketMap.has(id)) {
            dataSocket.end()
            dataSocketMap.delete(id)
        }

    })

    localSocket.on('error', function (err) {
        console.log('localSocket on error [%s] : %s', id, err.message)
        localSocketMap.delete(id)
        localSocket.end()
        localSocket.destroy()
        if (dataSocketMap.has(id)) {
            dataSocket.end()
            dataSocket.destroy()
            dataSocketMap.delete(id)
        }

    })

    dataSocket.on('data', function (data) {
        console.log('>> data : %s  -- %s', id, data.length)
        localSocket.write(data)
    })

    dataSocket.on('close', function () {
        console.log('dataSocket onClose %s', id)
        dataSocketMap.delete(id)

        localSocket.end()
        localSocketMap.delete(id)

    })

    dataSocket.on('error', function (err) {
        console.log('dataSocket on error [%s] : %s', id, err.message)
        dataSocketMap.delete(id)
        dataSocket.end()
        dataSocket.destroy()

        localSocket.end()
        localSocket.destroy()
    })


}

getClient()